package com.example.demo.concurrent.MyThreadPool2;

import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.concurrent.TimeUnit;

@FunctionalInterface //拒绝策略
interface RejectPolicy<T>{
    void reject(MyBlockingQueue<T> queue,T task);
}

@Slf4j(topic = "c.MyThreadPool")
public class MyThreadPool{
    //任务队列 -> 所有的任务全部放在BlockingQueue这个组件里面
    private MyBlockingQueue<Runnable> taskQueue;
    //工作线程的集合
    private HashSet<Worker> workers = new HashSet<>();
    //核心线程数
    private int coreSize;
    //超时时间,如果超过超时时间没有任务了,线程如果还要运行就会耗费性能
    private long timeout;
    //超时时间单位
    private TimeUnit unit;
    //拒绝策略
    private  RejectPolicy<Runnable> rejectPolicy;

    public MyThreadPool(int coreSize, long timeout, TimeUnit unit,int capacity,
                        RejectPolicy<Runnable> rejectPolicy) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.unit = unit;
        this.taskQueue = new MyBlockingQueue<>(capacity);
        this.rejectPolicy = rejectPolicy;
    }

    //执行任务
    public void execute(Runnable task) {
        synchronized (workers) {
            //如果任务不超过线程核心数
            if(workers.size() < coreSize) {
                //交给核心线程去执行
                Worker worker = new Worker(task);
                //加到线程集合中
                log.debug("新增worker{},{}",worker,task);
                workers.add(worker);
                worker.start();
            }else {
                //否则,任务数量超过线程核心数 , 把任务放到任务队列中
                //1.队列满了就死等
                //2.放弃任务的执行
                //3.抛出异常
                //4.调用者自己去执行任务
                //5.带超时的等待
                taskQueue.tryPut(rejectPolicy,task);
            }
        }
    }

    //工作线程
    class Worker extends Thread{
        private Runnable task;

        public Worker(Runnable task) {
            this.task = task;
        }

        @Override
        public void run() {
            //如果任务不为空,执行任务
            //接着从任务队列中取出任务,继续执行
            while(task!=null || (task = taskQueue.pool(timeout,unit))!=null) {
                try{
                    log.debug("任务执行中{}",task);
                    task.run();
                }catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            //线程执行完任务,从线程集合中移除
            synchronized (workers) {
                log.debug("移除线程{}",this);
                workers.remove(this);
            }
        }
    }
}